/*********************************************************************************
 *      Copyright:  (C) 2025 TBW
 *                  All rights reserved.
 *
 *       Filename:  shang_H_X.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(21/05/25)
 *         Author:  huang zixiao
 *      ChangeLog:  1, Release initial version on "21/05/25 15:47:50"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 计算信源熵的函数
double calculateEntropy(double *probabilities, int size) 
{
    double entropy = 0.0;

    for (int i = 0; i < size; i++) 
	{
        if (probabilities[i] > 0) 
		{
            // 计算每个符号的熵贡献并累加
            entropy -= probabilities[i] * log2(probabilities[i]);
        }
    }

    return entropy;
}

int main() 
{
    int n;
    printf("请输入信源符号的数量: ");
    if (scanf("%d", &n) != 1 || n <= 0)
	{
        fprintf(stderr, "错误：符号数量必须为正整数\n");
        return EXIT_FAILURE;
    }

    // 动态分配内存存储概率分布
    double *probabilities = (double *)malloc(n * sizeof(double));
    if (probabilities == NULL) 
	{
        fprintf(stderr, "内存分配失败\n");
        return EXIT_FAILURE;
    }

    printf("请依次输入每个符号的概率（用空格分隔）:\n");
    double sum = 0.0;
    for (int i = 0; i < n; i++) 
	{
        if (scanf("%lf", &probabilities[i]) != 1 || probabilities[i] < 0) 
		{
            fprintf(stderr, "错误：概率必须为非负实数\n");
            free(probabilities);
            return EXIT_FAILURE;
        }
        sum += probabilities[i];
    }

    // 检查概率和是否接近1（考虑浮点数精度问题）
    const double EPSILON = 1e-6;
    if (fabs(sum - 1.0) > EPSILON) 
	{
        fprintf(stderr, "错误：概率之和应为1，但计算结果为%lf\n", sum);
        free(probabilities);
        return EXIT_FAILURE;
    }

    // 计算并输出信源熵
    double entropy = calculateEntropy(probabilities, n);
    printf("该信源的熵为: %.6lf 比特/符号\n", entropy);

    // 释放动态分配的内存
    free(probabilities);

    return EXIT_SUCCESS;
}

